﻿using DEL;
using IBLL;
using IDAL;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;

//业务逻辑层，提供对数据访问层数据库增删查改基本功能的包装和重组，并提供给表示层
//本来应该以接口的方式，提供给表示层，此处因是小项目，省了
namespace BLL
{
    public abstract class BaseService<TEntity> : IBaseService<TEntity> where TEntity : BaseT, new()
    {

        protected static IBaseRepository<TEntity> CurrentRepository { get; set; }

        //基类的构造函数
        public BaseService()
        {
            SetCurrentRepository();  //构造函数里面去调用了，此设置当前仓储的抽象方法            
        }

        /// <summary>
        /// 子类必须实现
        /// </summary>
        public abstract void SetCurrentRepository();        
       

        #region 添加
        /// <summary>
        /// 实现对数据的添加功能
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public virtual int AddEntity(TEntity entity)
        {
            return CurrentRepository.AddEntity(entity);
        }
        public async Task<int> AddEntityAsync(TEntity entity)
        {
            return await CurrentRepository.AddEntityAsync(entity);
        }
        #endregion

        #region 修改
        /// <summary>
        /// 实现对数据的修改功能
        /// </summary>
        /// <param name="entity"></param>
        /// <returns>实体</returns>
        public virtual int ModifyEntity(TEntity entity)
        {            
            return CurrentRepository.ModifyEntity(entity);
        }
        public async Task<int> ModifyEntityAsync(TEntity entity)
        {
            return await CurrentRepository.ModifyEntityAsync(entity);
        }        
        #endregion

        #region 删除（伪删除）
        /// <summary>
        /// 实现对数据的删除功能,用修改的方法实现伪删除
        /// </summary>
        /// <param name="id"></param>
        /// <returns>被“删除”的实体</returns>
        public virtual bool DeleteEntityById(int id)
        {
            var entity = CurrentRepository.GetEntityById(id);
            entity.IsDeleted = true;            
            return ModifyEntity(entity)>0;            
        }
        public async virtual Task<bool> DeleteEntityByIdAsync(int id)
        {
            var entity = CurrentRepository.GetEntityById(id);
            entity.IsDeleted = true;           
            return await CurrentRepository.ModifyEntityAsync(entity)>0;
        }

        /// <summary>
        /// 根据条件对数据批量删除,用修改的方法实现伪删除
        /// </summary>
        /// <param name="whereLambda">条件表达式</param>
        public virtual bool DeleteEntitysByLambda(Expression<Func<TEntity, bool>> whereLambda)
        {
            try
            {
                var entitys = GetEntitysByLambda(whereLambda).ToList();
                foreach (TEntity entity in entitys)
                {
                    entity.IsDeleted = true;
                    ModifyEntity(entity);
                }
                return true;
            }
            catch
            {
                return false;
            }
        }
        public async virtual Task<bool> DeleteEntitysByLambdaAsync(Expression<Func<TEntity, bool>> whereLambda)
        {
            try
            {
                var entitys = GetEntitysByLambda(whereLambda).ToList();
                foreach (TEntity entity in entitys)
                {
                    entity.IsDeleted = true;
                    await ModifyEntityAsync(entity);
                }
                return true;
            }
            catch
            {
                return false;
            }
        }
        #endregion

        #region 查询
        /// <summary>
        /// 根据主键获取实体
        /// </summary>
        /// <param name="id">实体主键</param>
        /// <returns></returns>
        public virtual TEntity GetEntityById(int id)
        {
            return CurrentRepository.GetEntityById(id);
        }

        public virtual Task<TEntity> GetEntityByIdAsync(int id)
        {
            return CurrentRepository.GetEntityByIdAsync(id);
        }

        /// <summary>
        /// 获取所有实体，排序字段为'Id'(实体基类中含有Id字段),对数据巨大的表 慎用
        /// </summary>        
        public virtual IEnumerable<TEntity> GetAllEntitysList()
        {
            return GetEntitysByLambda(o => o.Id > 0);
        }        

        /// <summary>
        /// 根据条件获取一定数量的实体集合，慎用，排序字段和顺序默认
        /// </summary> 
        public virtual IEnumerable<TEntity> GetAnyEntitysList(int count, Expression<Func<TEntity, bool>> whereLambda)
        {
            return GetEntitysByLambda(whereLambda).Take(count);
        }

        /// <summary>
        /// 根据条件获取实体，排序字段和顺序默认       
        /// </summary>
        /// <param name="whereLambda">查询条件</param>
        /// <returns>实体的IQueryable语句</returns>
        public virtual IQueryable<TEntity> GetEntitysByLambda(Expression<Func<TEntity, bool>> whereLambda)  //IQueryable接口不会执行，方便后继继续使用SQL语句处理，IList已经执行数据库则不能了
        {
            return GetEntitysByLambdaAndSort(whereLambda, o=>o.Id, true);
        }

        /// <summary>
        ///实现数据的查询并排序
        /// </summary>
        /// <param name="whereLambda">查询条件</param>
        /// <param name="orderByLambda">排序字段，数据库中必须存在，不能为空，区分大小写</param>
        /// <param name="isAsc">如何排序，根据倒叙还是升序,true升序</param>
        /// <returns></returns>
        public virtual IQueryable<TEntity> GetEntitysByLambdaAndSort(Expression<Func<TEntity, bool>> whereLambda, Expression<Func<TEntity, object>> orderLambda, bool isAsc)
        {
            return CurrentRepository.GetEntitysByLambdaAndSort(whereLambda, orderLambda, isAsc);
        }
        #endregion

        #region 分页查询        
        /// <summary>
        /// 实现对数据的分页查询
        /// </summary>
        /// <param name="pageIndex">当前第几页</param>
        /// <param name="pageSize">一页显示多少条数据</param>
        /// <param name="rowCount">总条数</param> 
        /// <param name="pageCount">总页数</param> 
        /// <param name="whereLambda">条件表达式</param>
        /// <param name="isAsc">如何排序，根据倒叙还是升序</param>
        /// <param name="orderByLambda">排序字段</param>
        /// <returns></returns>
        public virtual List<TEntity> GetPagedEntitysByLambdaAndSort(int pageIndex, int pageSize, out int rowCount,out int pageCount, Expression<Func<TEntity, bool>> whereLambda, Expression<Func<TEntity, object>> orderLambda, bool isAsc)
        {
            return CurrentRepository.GetPagedEntitysByLambdaAndSort(pageIndex, pageSize, out rowCount, out pageCount, whereLambda, orderLambda, isAsc).ToList();
        }
                     
        #endregion
    }
}
